package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.cache.Cache;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.ServiceInventoryCheckMapper;
import com.eastfair.venueservice.dto.ServiceInventoryCheckDTO;
import com.eastfair.venueservice.dto.ServiceInventoryCheckDetailDTO;
import com.eastfair.venueservice.dto.ServiceInventoryCheckQuery;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.entity.ServiceInventoryCheck;
import com.eastfair.venueservice.entity.ServiceInventoryCheckDetail;
import com.eastfair.venueservice.enumeration.ServiceInventoryCheckCheckStateEnum;
import com.eastfair.venueservice.service.ServiceInventoryCheckDetailService;
import com.eastfair.venueservice.service.ServiceInventoryCheckService;
import com.eastfair.venueservice.vo.ServiceInventoryCheckDetailVO;
import com.eastfair.venueservice.vo.ServiceInventoryCheckVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* <p>
    * 业务实现类
    * 盘点记录
    * </p>
*
* @author linan
* @date 2022-09-19
*/
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceInventoryCheckServiceImpl extends SuperServiceImpl<ServiceInventoryCheckMapper, ServiceInventoryCheck> implements ServiceInventoryCheckService {

    public static final String PD = "PD";
    public static final String CHECK_NO = "check_no";
    @Resource
    private ServiceInventoryCheckDetailService serviceInventoryCheckDetailService;

    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
    */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceInventoryCheck> modelList) {
    modelList.stream().forEach(s -> {
    s.setIsDeleted(BusinessConstant.YES);
    });
    // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
    return R.successDef();
    }



    @Override
    protected R<Boolean> handlerSave(ServiceInventoryCheck model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    /**
    * 通用查询
    *
    * @param modelDTO DTO
    * @param ids 主键id集合
    * @return list
    */
    @Override
    public List<ServiceInventoryCheck> list(ServiceInventoryCheckDTO modelDTO, List<Long> ids) {
        return ((ServiceInventoryCheckService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids 主键id集合
     * @return list
     */
    @Override
    @Cache(key = "",
       magic = @Magic(
       key = "{"+
       "{'isEnabled', #args[0]?.isEnabled},"+
       "{'preparedBy', #args[0]?.preparedBy},"+
       "{'checkNo', #args[0]?.checkNo},"+
       "{'startDate', #args[0]?.startDate},"+
       "{'endDate', #args[0]?.endDate},"+
       "{'systemTotalNum', #args[0]?.systemTotalNum},"+
       "{'checkTotalNum', #args[0]?.checkTotalNum},"+
       "{'surplusTotalNum', #args[0]?.surplusTotalNum},"+
       "{'lossTotalNum', #args[0]?.lossTotalNum},"+
       "{'checkState', #args[0]?.checkState},"+
        "{'id', #args[1]}"+
        "}"))
    public List<ServiceInventoryCheck> listOfCache(ServiceInventoryCheckDTO modelDTO, List<Long> ids) {
       //查询
       QueryWrapper<ServiceInventoryCheck> queryWrapper = new QueryWrapper<>();
       if (modelDTO != null) {
                    queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getCheckNo()),ServiceInventoryCheck::getCheckNo,modelDTO.getCheckNo());
                    queryWrapper.lambda().eq(modelDTO.getStartDate() != null,ServiceInventoryCheck::getStartDate,modelDTO.getStartDate());
                    queryWrapper.lambda().eq(modelDTO.getEndDate() != null,ServiceInventoryCheck::getEndDate,modelDTO.getEndDate());
                    queryWrapper.lambda().eq(modelDTO.getSystemTotalNum() != null,ServiceInventoryCheck::getSystemTotalNum,modelDTO.getSystemTotalNum());
                    queryWrapper.lambda().eq(modelDTO.getCheckTotalNum() != null,ServiceInventoryCheck::getCheckTotalNum,modelDTO.getCheckTotalNum());
                    queryWrapper.lambda().eq(modelDTO.getSurplusTotalNum() != null,ServiceInventoryCheck::getSurplusTotalNum,modelDTO.getSurplusTotalNum());
                    queryWrapper.lambda().eq(modelDTO.getLossTotalNum() != null,ServiceInventoryCheck::getLossTotalNum,modelDTO.getLossTotalNum());
            }
            if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(ServiceInventoryCheck::getId, ids);
            }
            queryWrapper.lambda().eq(ServiceInventoryCheck::getIsDeleted, BusinessConstant.DELETE_NO);
            List<ServiceInventoryCheck> modelList = list(queryWrapper);
            return modelList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveInventoryCheck(ServiceInventoryCheckDTO serviceInventoryCheckSaveDTO) {
        List<ServiceInventoryCheckDetailDTO> serviceInventoryCheckDetails = serviceInventoryCheckSaveDTO.getServiceInventoryCheckDetails();
        dealNums(serviceInventoryCheckDetails, serviceInventoryCheckSaveDTO);
        ServiceInventoryCheck serviceInventoryCheck = BeanUtil.copyProperties(serviceInventoryCheckSaveDTO,ServiceInventoryCheck.class,CommonConstants.COMMON_IGNORE_PROPERTIES);
        boolean save = save(serviceInventoryCheck);
        for (ServiceInventoryCheckDetailDTO serviceInventoryCheckDetail : serviceInventoryCheckDetails) {
            ServiceInventoryCheckDetail serviceInventoryCheckDetail1 = BeanUtil.copyProperties(serviceInventoryCheckDetail, ServiceInventoryCheckDetail.class,CommonConstants.COMMON_IGNORE_PROPERTIES);
            serviceInventoryCheckDetail1.setCheckNo(serviceInventoryCheck.getCheckNo());
            serviceInventoryCheckDetailService.save(serviceInventoryCheckDetail1);
        }
        return save;
    }

    private void dealNums(List<ServiceInventoryCheckDetailDTO> serviceInventoryCheckDetails, ServiceInventoryCheckDTO serviceInventoryCheckDTO) {
        // 总系统库存
        double systemTotalNum = serviceInventoryCheckDetails.stream().mapToDouble(e -> e.getSystemNum().doubleValue()).sum();
        // 总盘点库存
        double checkTotalNum = serviceInventoryCheckDetails.stream().mapToDouble(e -> e.getCheckNum().doubleValue()).sum();
        // 总盘盈数量
        double surplusTotalNum = serviceInventoryCheckDetails.stream().mapToDouble(e -> e.getSurplusNum().doubleValue()).sum();
        // 总盘亏数量
        double lossTotalNum = serviceInventoryCheckDetails.stream().mapToDouble(e -> e.getLossNum().doubleValue()).sum();
        serviceInventoryCheckDTO.setSystemTotalNum(BigDecimal.valueOf(systemTotalNum));
        serviceInventoryCheckDTO.setCheckTotalNum(BigDecimal.valueOf(checkTotalNum));
        serviceInventoryCheckDTO.setSurplusTotalNum(BigDecimal.valueOf(surplusTotalNum));
        serviceInventoryCheckDTO.setLossTotalNum(BigDecimal.valueOf(lossTotalNum));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateInventoryCheck(ServiceInventoryCheckDTO serviceInventoryCheckDTO) {
        List<ServiceInventoryCheckDetailDTO> serviceInventoryCheckDetails = serviceInventoryCheckDTO.getServiceInventoryCheckDetails();
        // 总系统库存
        dealNums(serviceInventoryCheckDetails, serviceInventoryCheckDTO);
        ServiceInventoryCheck serviceInventoryCheck = BeanUtil.copyProperties(serviceInventoryCheckDTO,ServiceInventoryCheck.class);
        boolean update = updateById(serviceInventoryCheck);
        // 删除历史明细，并重新插入
        serviceInventoryCheckDetailService.update(new UpdateWrapper<ServiceInventoryCheckDetail>().lambda()
                .eq(ServiceInventoryCheckDetail::getCheckNo,serviceInventoryCheckDTO.getCheckNo())
                .eq(ServiceInventoryCheckDetail::getIsDeleted,BusinessConstant.NO)
                .set(ServiceInventoryCheckDetail::getIsDeleted,BusinessConstant.YES));
        for (ServiceInventoryCheckDetailDTO serviceInventoryCheckDetail : serviceInventoryCheckDetails) {
            ServiceInventoryCheckDetail serviceInventoryCheckDetail1 = BeanUtil.copyProperties(serviceInventoryCheckDetail, ServiceInventoryCheckDetail.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
            serviceInventoryCheckDetailService.save(serviceInventoryCheckDetail1);
        }
        return update;
    }

    @Override
    public String queryNewCheckNo() {
        return CreatCode.creatCode(baseMapper, CHECK_NO,10, PD);
    }

    @Override
    public Boolean delInventoryCheck(ServiceInventoryCheckDTO serviceInventoryCheckDTO) {
        Long id = serviceInventoryCheckDTO.getId();
        ServiceInventoryCheck inventoryCheck = this.getById(id);
        if(Objects.nonNull(inventoryCheck)){
            this.removeByIdsOfLogic(Collections.singletonList(inventoryCheck));
            serviceInventoryCheckDetailService.update(new UpdateWrapper<ServiceInventoryCheckDetail>().lambda().eq(ServiceInventoryCheckDetail::getCheckNo,inventoryCheck.getCheckNo()).set(ServiceInventoryCheckDetail::getIsDeleted,BusinessConstant.YES));
        }
        return true;
    }

    @Override
    public Page<ServiceInventoryCheckVO> queryCheckList(PageParams<ServiceInventoryCheckQuery> serviceInventoryCheckQuery) {
        serviceInventoryCheckQuery.setSort(null);
        serviceInventoryCheckQuery.setOrder(null);
        Page<ServiceInventoryCheckQuery> page = serviceInventoryCheckQuery.buildPage();
        ServiceInventoryCheckQuery model = serviceInventoryCheckQuery.getModel();
        LocalDate now = LocalDate.now();
        QueryWrapper<ServiceInventoryCheck> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(model.getCheckNo()),"a.check_no",model.getCheckNo())
                .ge(Objects.nonNull(model.getUpdateTimeBegin()), "a.update_time", model.getUpdateTimeBegin())
                .le(Objects.nonNull(model.getUpdateTimeEnd()), "a.update_time", model.getUpdateTimeEnd())
                .eq(Objects.nonNull(model.getExhibitionManageId()), "a.exhibition_manage_id", model.getExhibitionManageId())
                .eq(Objects.nonNull(model.getServiceProviderId()), "a.service_provider_id", model.getServiceProviderId())
                .eq("a.is_deleted", BusinessConstant.NO)
                .gt(StringUtils.isNotBlank(model.getCheckState()) && ServiceInventoryCheckCheckStateEnum.UN_START.getCode().equals(model.getCheckState()), "a.start_date", now)
                .lt(StringUtils.isNotBlank(model.getCheckState()) && ServiceInventoryCheckCheckStateEnum.FINISH.getCode().equals(model.getCheckState()), "a.end_date", now)
                .le(StringUtils.isNotBlank(model.getCheckState()) && ServiceInventoryCheckCheckStateEnum.UN_FINISH.getCode().equals(model.getCheckState()),"a.start_date", now)
                .ge(StringUtils.isNotBlank(model.getCheckState()) && ServiceInventoryCheckCheckStateEnum.UN_FINISH.getCode().equals(model.getCheckState()),"a.end_date", now)
                .groupBy("a.check_no")
                .orderByDesc("a.update_time");
        Page<ServiceInventoryCheckVO> result= baseMapper.queryCheckList(page, wrapper);
        List<Long> userIds = result.getRecords().stream().map(ServiceInventoryCheckVO::getCreatedBy).collect(Collectors.toList());
        UserAccountDto userAccountDto = new UserAccountDto();
        userAccountDto.setUserIds(userIds);
        //获取人员信息
        R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
        //把人员信息转成map
        if(Objects.nonNull(listR) && CollectionUtils.isNotEmpty(listR.getData())){
            Map<Long, UserAccountVo> userMap = listR.getData().stream().collect(Collectors.toMap(UserAccountVo::getId, Function.identity()));
            //获取分类下服务项数量
            if (Objects.nonNull(result.getRecords()) && result.getRecords().size()>0) {
                result.getRecords().forEach((s)->{
                    s.setCreatedByName(userMap.get(s.getCreatedBy()).getRealName());
                    if(now.compareTo(s.getStartDate())<0){
                        s.setCheckState(ServiceInventoryCheckCheckStateEnum.UN_START);
                    }else if(now.compareTo(s.getEndDate())>0){
                        s.setCheckState(ServiceInventoryCheckCheckStateEnum.FINISH);
                    }else {
                        s.setCheckState(ServiceInventoryCheckCheckStateEnum.UN_FINISH);
                    }
                });
            }
        }
        return result;
    }

    @Override
    public ServiceInventoryCheckVO queryCheckDetailList(ServiceInventoryCheckQuery serviceInventoryCheckQuery) {
        ServiceInventoryCheck serviceInventoryCheck = getOne(new QueryWrapper<ServiceInventoryCheck>().lambda()
                .eq(ServiceInventoryCheck::getCheckNo, serviceInventoryCheckQuery.getCheckNo())
                .eq(ServiceInventoryCheck::getIsDeleted, BusinessConstant.NO));
        if(Objects.nonNull(serviceInventoryCheck)){
            ServiceInventoryCheckVO serviceInventoryCheckVO = BeanUtil.copyProperties(serviceInventoryCheck, ServiceInventoryCheckVO.class);
            List<ServiceInventoryCheckDetailVO> serviceInventoryCheckDetailVO= serviceInventoryCheckDetailService.queryCheckDetailList(serviceInventoryCheck);
            serviceInventoryCheckVO.setServiceInventoryCheckDetailList(serviceInventoryCheckDetailVO);
            UserAccountDto userAccountDto = new UserAccountDto();
            userAccountDto.setUserIds(Collections.singletonList(serviceInventoryCheck.getCreatedBy()));
            //获取人员信息
            R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
            if (listR.getIsSuccess() && CollectionUtils.isNotEmpty(listR.getData())) {
                serviceInventoryCheckVO.setCreatedByName(listR.getData().get(0).getRealName());
            }
            return serviceInventoryCheckVO;
        }
        return null;
    }


    /**
     * do转vo
     * @param model model
     * @return modelVo
     */
    @Override
    public ServiceInventoryCheckVO doToVo(ServiceInventoryCheck model) {
        ServiceInventoryCheckVO modelVo = new ServiceInventoryCheckVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }
    /**
     * do转vo
     * @param modelList modelList
     * @return list
     */
     @Override
     public List<ServiceInventoryCheckVO> doToVos(List<ServiceInventoryCheck> modelList) {
        if (modelList == null || modelList.isEmpty()) {
        return null;
        }
        List<ServiceInventoryCheckVO> result = new ArrayList<>();
        for (ServiceInventoryCheck model : modelList) {
           result.add(doToVo(model));
        }
        return result;
    }
}
